// commodityCollectionMgr.js
import { CsDouble } from '../common/csDouble.js';
import { CsFundDouble } from '../common/csFundDouble.js';
import { Commodity } from './commodity.js';
import { SubCommodity } from './subCommodity.js';
import { CommodityBatch } from '../inventory/inventory.js';
import { CommodityBatchWithTax } from '../sales/sales.js';
import { CommodityCollection, CommodityCollectionCode } from './commodityCollection.js';
import { SubCommodityCollection, SubCommodityCollectionPriceMode } from './subcommodityCollection.js';

/**
 * 商品选择模式枚举
 */
export const CollectionMgrSelectionMode = {
    salesMode: 0,       // 销售模式，显示零售和批发价
    purchaseMode: 1,    // 采购模式，显示采购价
    inventoryIn: 2,     // 入库模式，显示采购价
    inventoryOut: 3,    // 出库模式，显示零售批发价
    inventoryOnly: 4,   // 库存模式，显示数量，不显示价格
    inventorySheetMode: 5 // 盘点模式，显示库存及盈亏
};

/**
 * 商品集合管理器
 */
export class CommodityCollectionMgr {
    constructor() {
        /** @type {Array<CommodityCollection>} */
        this._commodityCollection = [];

        /** @type {Array<Function>} 观察者列表 */
        this._listeners = [];
    }


    /**
 * 添加数据变更监听器
 * @param {Function} listener 监听回调函数
 * @returns {Function} 取消监听的方法
 */
    addListener(listener) {
        if (typeof listener !== 'function') {
            console.warn('Listener must be a function');
            return () => { };
        }

        this._listeners.push(listener);

        // 返回取消监听的函数
        return () => {
            this._listeners = this._listeners.filter(l => l !== listener);
        };
    }


    /**
  * 通知所有监听器数据已更新
  */
    dataUpdated() {
        // 复制监听器数组以避免在通知过程中修改数组
        const listeners = [...this._listeners];
        listeners.forEach(listener => {
            try {
                listener();
            } catch (error) {
                console.error('Error in collection manager listener:', error);
            }
        });
    }

    /**
     * 获取商品集合列表（只读）
     * @returns {Array<CommodityCollection>}
     */
    get commodityCollection() {
        return Object.freeze([...this._commodityCollection]);
    }

    /**
     * 克隆当前管理器
     * @param {CommodityCollectionMgr} source 
     * @returns {CommodityCollectionMgr}
     */
    static clone(source) {
        const cloned = new CommodityCollectionMgr();
        source._commodityCollection.forEach(item => {
            cloned._commodityCollection.push(CommodityCollection.clone(item));
        });
        return cloned;
    }

    /**
     * 从含税商品批次列表构造
     * @param {Array<CommodityBatchWithTax>} batchs 
     * @param {Object} options
     * @param {SubCommodityCollectionPriceMode} options.priceMode 价格模式
     * @returns {CommodityCollectionMgr}
     */
    static fromCommodityBatchsWithTax({ batchs, priceMode }) {
        const mgr = new CommodityCollectionMgr();
        batchs.forEach(batch => {
            const commodityCollection = mgr.getOrCreateCommodityCollection(
                {
                    commodity: batch.commodity.commodity || new Commodity({ id: batch.commodity.commodityId }),
                    insertIfNotExist: true
                }
            );
            // 获取或创建子商品集，如果需要创建新子商品集，则不创建 默认 batch,
            const subCommodityCollection = commodityCollection.getOrCreateSubCommodityCollection({
                subCommodity: batch.commodity,
                insertIfNotExist: true,
                initSubCommodityBatch: false,
                priceMode,
                inventoryCount: batch.inventoryCount
            });

            subCommodityCollection.addSubCommodityBatchWithTax(batch);
        });
        return mgr;
    }

    /**
     * 从商品批次列表构造
     * @param {Array<CommodityBatch>} batchs 
     * @param {Object} options
     * @param {SubCommodityCollectionPriceMode} options.priceMode 价格模式
     * @param {boolean} options.withoutTaxForce 是否强制使用不含税价格 (用于出入库时的价格计算)
     * @returns {CommodityCollectionMgr}
     */
    static fromCommodityBatchs({ batchs, priceMode, withoutTaxForce = false }) {
        const mgr = new CommodityCollectionMgr();
        batchs.forEach(batch => {
            const commodityCollection = mgr.getOrCreateCommodityCollection(
                {
                    commodity: batch.commodity.commodity || new Commodity({ id: batch.commodity.commodityId }),
                    insertIfNotExist: true
                }
            );

            // 获取或创建子商品集，如果需要创建新子商品集，则不创建 默认 batch,
            const subCommodityCollection = commodityCollection.getOrCreateSubCommodityCollection({
                subCommodity: batch.commodity,
                insertIfNotExist: true,
                initSubCommodityBatch: false,
                priceMode,
                inventoryCount: batch.inventoryCount,
                withoutTaxForce: withoutTaxForce,
            });
            // 添加batch (所以不创建默认batch)
            subCommodityCollection.addSubCommodityBatch(batch);
        });
        return mgr;
    }

    /**
     * 获取有效商品种类数量
     * @returns {number}
     */
    getValideCollectionCount() {
        return this._commodityCollection.filter(
            item => item.getCommodityCount().value !== 0
        ).length;
    }

    /**
     * 添加商品集合
     * @param {CommodityCollection} collection 
     * @returns {CommodityCollectionCode}
     */
    addCommodityCollection(collection) {
        // 重复检测
        if (this._commodityCollection.some(
            item => item.commodity.id === collection.commodity.id)) {
            return CommodityCollectionCode.CommodityCollectionDuplicated;
        }
        this._commodityCollection.push(collection);
        return CommodityCollectionCode.Succeed;
    }

    /**
     * 初始化商品集合
     * @param {Array<CommodityCollection>} collections 
     */
    initCollection(collections) {
        this._commodityCollection = [];
        collections.forEach(item => this.addCommodityCollection(item));
    }

    /**
     * 获取商品集合
     * @param {string} commodityId 
     * @returns {CommodityCollection|null}
     */
    getCommodityCollection(commodityId) {
        return this._commodityCollection.find(
            item => item.commodity.id === commodityId) || null;
    }

    /**
     * 获取单规格商品集合
     * @param {string} commodityId 
     * @returns {SubCommodityCollection|null}
     */
    getSingleStanderdCollection(commodityId) {
        const item = this.getCommodityCollection(commodityId);
        if (item && item.subCommmodityCollectionList.length === 1) {
            return item.subCommmodityCollectionList[0];
        }
        return null;
    }

    /**
     * 获取或创建商品集合
     * @param {Object} params
     * @param {Commodity} params.commodity 商品
     * @param {boolean} params.insertIfNotExist 是否自动插入
     * @returns {CommodityCollection}
     */
    getOrCreateCommodityCollection({ commodity, insertIfNotExist }) {
        let collection = this.getCommodityCollection(commodity.id);
        if (!collection && insertIfNotExist) {
            collection = new CommodityCollection({ commodity });
            this._commodityCollection.push(collection);
        }
        return collection || new CommodityCollection({ commodity });
    }

    /**
     * 获取或创建单规格商品集合
     * @param {Object} params
     * @param {SubCommodity} params.subCommodity 子商品
     * @param {Commodity} params.commodity 商品
     * @param {boolean} params.insertIfNotExist 是否自动插入
     * @param {SubCommodityCollectionPriceMode} params.priceMode 价格模式
     * @returns {SubCommodityCollection}
     */
    getOrCreateSingleStanderdCollection({
        subCommodity,
        commodity,
        insertIfNotExist,
        priceMode,
        // 创建时是否强制不包含税 (出入库商品选择时用)
        withoutTaxForce = false
    }) {
        const collection = this.getOrCreateCommodityCollection({ commodity, insertIfNotExist });
        return collection.getOrCreateSubCommodityCollection({
            subCommodity,
            insertIfNotExist,
            priceMode,
            inventoryCount: commodity.count,
            withoutTaxForce: withoutTaxForce
        });
    }

    /**
     * 获取商品总数量
     * @returns {CsDouble}
     */
    getCommodityCount() {
        let totalCount = CsDouble.zero();
        this._commodityCollection.forEach(item => {
            totalCount = totalCount.add(item.getCommodityCount());
        });
        return totalCount;
    }

    /**
     * 获取商品总价
     * @returns {CsFundDouble}
     */
    getCommodityPrice() {
        let totalPrice = CsFundDouble.zero();
        this._commodityCollection.forEach(item => {
            totalPrice = totalPrice.add(item.getCommodityPrice());
        });
        return totalPrice;
    }

    /**
     * 获取所有规格商品批次
     * @param {Object} options
     * @param {boolean} [options.zeroInclude=false] 是否包含0数量
     * @returns {Array<CommodityBatchWithTax>}
     */
    getSubCommodityBatches({ zeroInclude = false } = {}) {
        return this._commodityCollection.flatMap(item =>
            item.getSubCommodityBatches({ zeroInclude })
        );
    }

    /**
     * 移除规格商品批次
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    removeSubCommodityBatch(batch) {
        const collection = this.getCommodityCollection(
            batch.commodity.commodity?.id || batch.commodity.commodityId
        );
        return collection ? collection.removeSubCommodityBatch(batch) : false;
    }

    /**
     * 添加或创建规格商品批次
     * @param {Object} params
     * @param {CommodityBatchWithTax|null} params.orgBatch 原有批次
     * @param {CommodityBatchWithTax} params.batch 新批次
     */
    addOrCreateSubCommodityBatch({ orgBatch, batch }) {
        if (orgBatch && orgBatch.commodity.id !== batch.commodity.id) {
            console.warn("CommodityCollectionMgr::addOrCreateSubCommodityBatch - orgBatch commodity not match batch commodity");
            return;
        }

        if (!batch || !batch.commodity) {
            console.warn("Invalid batch parameter");
            return;
        }

        const commodityCollection = this.getCommodityCollection(
            batch.commodity.commodity?.id || batch.commodity.commodityId
        );

        if (commodityCollection) {
            const subCommodityCollection = commodityCollection.getSubCommodityCollection(batch.commodity.id);
            if (subCommodityCollection) {
                subCommodityCollection.addOrCreateSubCommodityBatch({
                    orgBatch,
                    batch
                });
            } else {
                console.warn("CommodityCollectionMgr::addOrCreateSubCommodityBatch - subCommodityCollection not found");
            }
        }
    }
}